package models

import (
	"errors"
	"go-jhb-admin-api/app/utils"
	"go-jhb-admin-api/config"
	"math"
	"os"
	"time"

	"gorm.io/gorm"
)

// Admin 表示管理员表
type Admin struct {
	ID         uint   `gorm:"primaryKey;autoIncrement;not null" json:"id"`
	Account    string `gorm:"type:varchar(255);not null;index;comment:账号" json:"account"`
	Password   string `gorm:"type:varchar(255);not null;comment:密码" json:"password"`
	Name       string `gorm:"type:varchar(125);default:'';comment:姓名" json:"name"`
	Status     uint8  `gorm:"type:tinyint unsigned;not null;default:1;comment:1:正常 0:禁用" json:"status"`
	Roles      string `gorm:"type:varchar(255);not null;default:'';comment:角色" json:"roles"`
	LastIP     string `gorm:"type:varchar(35);not null;default:'';comment:最后登录ip" json:"last_ip"`
	LastTime   uint   `gorm:"type:int unsigned;not null;default:0;comment:最后登录时间" json:"last_time"`
	CreateTime uint   `gorm:"type:int unsigned;not null;default:0;comment:创建时间" json:"create_time"`
	UpdateTime uint   `gorm:"type:int unsigned;not null;default:0;comment:更新时间" json:"update_time"`
	DeleteTime uint   `gorm:"type:int unsigned;not null;default:0;comment:删除时间" json:"delete_time"`
}

// TableName 自定义表名
func (Admin) TableName() string {
	tablePrefix := os.Getenv("DB_PREFIX") // 从环境变量或配置文件中获取前缀
	return tablePrefix + "admin"
}

// GetByID 根据id获取管理员详情
func (admin *Admin) GetByID(id uint) error {
	// 查询管理员信息
	if err := config.DB.Where("id = ?", id).Scopes(DeleteTime).First(admin).Error; err != nil {
		// 如果没有找到，返回一个自定义错误
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("数据不存在")
		}
		// 其他错误返回
		return err
	}
	// 屏蔽password字段
	admin.Password = ""
	return nil
}

// 获取管理员列表(分页)
func (admin *Admin) GetAdmins(page, limit int, filters map[string]interface{}) ([]Admin, int64, int, int, error) {
	var admins []Admin

	// 设置查询条件
	query := config.DB.Model(&Admin{})

	// 根据 filters 添加其他条件
	for key, value := range filters {
		query = query.Where(key+" = ?", value)
	}

	// 获取总记录数
	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, 0, 0, err
	}

	// 计算总页数
	totalPages := int(math.Ceil(float64(total) / float64(limit)))

	// 执行分页查询
	if err := query.Offset((page - 1) * limit).Limit(limit).Find(&admins).Error; err != nil {
		return nil, 0, 0, 0, err
	}

	return admins, total, totalPages, page, nil
}

// 添加/编辑 管理员
func (admin *Admin) AddOrUpdateAdmin() error {

	if admin.Account == "" {
		return errors.New("请输入登录账号")
	}

	// 创建时必须要输入密码
	if admin.ID == 0 {
		if admin.Password == "" {
			return errors.New("密码不能为空")
		}

		// 判断账号是否重复
		var existingAdmin Admin
		if err := config.DB.Where("account = ?", admin.Account).Select("id").First(&existingAdmin).Error; err == nil {
			// 如果 err 为 nil，说明找到了一条记录，表示账号已存在
			return errors.New("账号已存在")
		} else if !errors.Is(err, gorm.ErrRecordNotFound) {
			// 如果错误不是记录未找到错误，表示查询发生其他问题
			return err
		}
	}

	// 处理密码加密
	if admin.Password != "" {
		admin.Password = utils.GeneratePassword(admin.Password)
	}

	validStatuses := map[uint8]bool{
		0: true,
		1: true,
	}

	// 判断 status 是否有效
	if !validStatuses[admin.Status] {
		return errors.New("无效的状态")
	}

	// 如果管理员的 ID 为 0，表示是添加操作
	if admin.ID == 0 {
		// 设置创建时间
		admin.CreateTime = uint(time.Now().Unix())
		admin.UpdateTime = admin.CreateTime
		if err := config.DB.Create(admin).Error; err != nil {
			return err
		}
	} else {

		// 如果密码为空，保持原密码不变
		if admin.Password == "" {
			var existingAdmin Admin
			if err := config.DB.Where("id = ?", admin.ID).First(&existingAdmin).Error; err != nil {
				return err
			}
			admin.Password = existingAdmin.Password // 保持原密码不变
		}

		// 编辑操作，先设置更新时间
		admin.UpdateTime = uint(time.Now().Unix())
		if err := config.DB.Save(admin).Error; err != nil {
			return err
		}
	}

	return nil
}

func DeleteAdmin(id uint) error {

	if id == 0 {
		return errors.New("ID 错误")
	}

	// 查询数据
	var admin Admin

	if err := admin.GetByID(id); err != nil {
		return errors.New(err.Error())
	}

	updateData := map[string]interface{}{
		"delete_time": uint(time.Now().Unix()),
	}

	if err := config.DB.Model(&Admin{}).Where("id = ?", admin.ID).Updates(updateData).Error; err != nil {
		return err
	}

	return nil
}
